package com.stellar.circle.domain.sChatRelationship.impl;

import com.stellar.auth.api.dto.UserInfoDTO;
import com.stellar.circle.basic.entity.SChatRelationship;
import com.stellar.circle.basic.service.SChatRelationshipService;
import com.stellar.circle.constants.ErrorCodeConstants;
import com.stellar.circle.controller.admin.sChatRelationship.vo.SChatRelationshipRequestPageVO;
import com.stellar.circle.controller.admin.sChatRelationship.vo.SChatRelationshipRequestVO;
import com.stellar.circle.controller.admin.sChatRelationship.vo.SChatRelationshipResponseVO;
import com.stellar.circle.convert.SChatRelationshipConvert;
import com.stellar.circle.domain.sChatRelationship.SChatRelationshipDomainService;
import com.stellar.circle.rpc.UserRPC;
import com.stellar.web.core.bean.PageResult;
import com.stellar.web.core.enums.IsDeletedFlagEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.stellar.circle.constants.CircleConstants.IS_BLOCKED_NO;
import static com.stellar.circle.constants.CircleConstants.IS_BLOCKED_YES;
import static com.stellar.core.util.ServiceExceptionUtil.exception;

/**
 * 用户聊天关系表领域服务实现
 *
 * @author Jqchan
 * @version 1.0
 * @date 2025-06-12 21:21:37
 */
@Service
@Slf4j
public class SChatRelationshipDomainServiceImpl implements SChatRelationshipDomainService {

    @Resource
    private SChatRelationshipService sChatRelationshipService;

    @Resource
    private UserRPC userRPC;

    @Override
    public PageResult<SChatRelationshipResponseVO> page(SChatRelationshipRequestPageVO requestPageVO) {
        PageResult<SChatRelationshipResponseVO> pageResult = new PageResult<>();
        SChatRelationship queryEntity = SChatRelationshipConvert.INSTANCE.convert(requestPageVO);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        List<SChatRelationship> entities = sChatRelationshipService.page(queryEntity,
                requestPageVO.getStart(), requestPageVO.getPageSize());

        if (entities.isEmpty()) {
            return pageResult;
        }

        Long count = sChatRelationshipService.count(queryEntity);
        List<SChatRelationshipResponseVO> vos = SChatRelationshipConvert.INSTANCE.convertEntityToRespList(entities);

        pageResult.setResult(vos);
        pageResult.setTotal(count.intValue());
        return pageResult;
    }

    @Override
    public Boolean update(SChatRelationshipRequestVO requestVO) {
        SChatRelationship entity = SChatRelationshipConvert.INSTANCE.convert(requestVO);
        return sChatRelationshipService.update(entity) != 0;
    }

    @Override
    public Boolean delete(Long id) {
        SChatRelationship entity = new SChatRelationship();
        entity.setId(id);
        entity.setIsDeleted(IsDeletedFlagEnum.DELETED.getVal());
        return sChatRelationshipService.update(entity) != 0;
    }

    @Override
    public Boolean insert(SChatRelationshipRequestVO requestVO) {
        SChatRelationship entity = SChatRelationshipConvert.INSTANCE.convert(requestVO);
        return sChatRelationshipService.insert(entity) != 0;
    }

    @Override
    public SChatRelationshipResponseVO get(Long id) {
        SChatRelationship entity = sChatRelationshipService.queryById(id);
        return SChatRelationshipConvert.INSTANCE.convert(entity);
    }

    @Override
    public Boolean addFriend(Long userId, Long friendId) {
        // 防止重复添加
        SChatRelationship queryEntity = new SChatRelationship();
        queryEntity.setUserId(userId);
        queryEntity.setFriendId(friendId);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        SChatRelationship sChatRelationship = sChatRelationshipService.queryByCondition(queryEntity);
        if (sChatRelationship != null) {
            throw exception(ErrorCodeConstants.CIRCLE_USER_RELATION_EXIST);
        }

        // 双向关系
        SChatRelationship rel1 = new SChatRelationship();
        rel1.setUserId(userId);
        rel1.setFriendId(friendId);
        rel1.setIsBlocked(IS_BLOCKED_NO);
        rel1.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        SChatRelationship rel2 = new SChatRelationship();
        rel2.setUserId(friendId);
        rel2.setFriendId(userId);
        rel2.setIsBlocked(IS_BLOCKED_NO);
        rel2.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());

        sChatRelationshipService.insert(rel1);
        sChatRelationshipService.insert(rel2);

        return true;
    }

    @Override
    public Boolean deleteFriend(Long userId, Long friendId) {
        // 双向删除
        SChatRelationship rel1 = new SChatRelationship();
        rel1.setUserId(userId);
        rel1.setFriendId(friendId);
        rel1.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        SChatRelationship sChatRelationship1 = sChatRelationshipService.queryByCondition(rel1);
        if (sChatRelationship1 != null) {
            sChatRelationshipService.update(rel1);
        }

        SChatRelationship rel2 = new SChatRelationship();
        rel2.setUserId(friendId);
        rel2.setFriendId(userId);
        rel2.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        SChatRelationship sChatRelationship2 = sChatRelationshipService.queryByCondition(rel2);
        if (sChatRelationship2 != null) {
            sChatRelationshipService.update(rel2);
        }
        return true;
    }

    @Override
    public Boolean blockOrUnblock(Long userId, Long friendId) {
        SChatRelationship queryEntity = new SChatRelationship();
        queryEntity.setUserId(userId);
        queryEntity.setFriendId(friendId);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        SChatRelationship sChatRelationship = sChatRelationshipService.queryByCondition(queryEntity);
        if (sChatRelationship == null) {
            return false;
        }
        // 状态转换
        if (Objects.equals(sChatRelationship.getIsBlocked(), IS_BLOCKED_YES)) { // 封禁 -> 解封
            sChatRelationship.setIsBlocked(IS_BLOCKED_NO);
            sChatRelationship.setBlockTime(null);
            sChatRelationshipService.update(sChatRelationship);
        } else { // 解封 -> 封禁
            sChatRelationship.setIsBlocked(IS_BLOCKED_YES);
            sChatRelationship.setBlockTime(new Date());
            sChatRelationshipService.update(sChatRelationship);
        }
        return true;
    }

    @Override
    public List<SChatRelationshipResponseVO> list(Long userId) {
        List<SChatRelationship> entities = sChatRelationshipService.queryAllByCondition(new SChatRelationship() {{
            setUserId(userId);
            setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        }});

        if (CollectionUtils.isEmpty(entities)) {
            return Collections.emptyList();
        }

        List<SChatRelationshipResponseVO> sChatRelationshipResponseVOS =
                SChatRelationshipConvert.INSTANCE.convertEntityToRespList(entities);

        // 提取所有好友ID
        List<Long> friendIds = sChatRelationshipResponseVOS.stream()
                .map(SChatRelationshipResponseVO::getFriendId)
                .collect(Collectors.toList());

        if (CollectionUtils.isEmpty(friendIds)) {
            return sChatRelationshipResponseVOS;
        }

        // 并行执行两个任务：获取用户信息和检查双方关系
        CompletableFuture<List<UserInfoDTO>> userInfoFuture = CompletableFuture.supplyAsync(() ->
                userRPC.batchQueryByIds(friendIds)
        );

        CompletableFuture<Set<Long>> mutualFuture = CompletableFuture.supplyAsync(() ->
                getMutualFriendIds(userId, friendIds)
        );

        // 等待所有任务完成并处理结果
        try {
            CompletableFuture.allOf(userInfoFuture, mutualFuture).get();

            // 处理用户信息
            List<UserInfoDTO> userInfoDTOS = userInfoFuture.get();
            if (!CollectionUtils.isEmpty(userInfoDTOS)) {
                Map<Long, UserInfoDTO> userInfoMap = userInfoDTOS.stream()
                        .collect(Collectors.toMap(UserInfoDTO::getId, Function.identity()));

                sChatRelationshipResponseVOS.forEach(vo -> {
                    UserInfoDTO userInfo = userInfoMap.get(vo.getFriendId());
                    if (userInfo != null) {
                        vo.setFriendNickName(userInfo.getNickName());
                        vo.setFriendAvatar(userInfo.getAvatar());
                    }
                });
            }

            // 处理双方关系
            Set<Long> mutualFriendIds = mutualFuture.get();
            sChatRelationshipResponseVOS.forEach(vo -> {
                vo.setIsMutual(mutualFriendIds.contains(vo.getFriendId()));
            });

        } catch (InterruptedException | ExecutionException e) {
            log.error("并行处理关注列表时发生异常", e);
            return Collections.emptyList();
        }

        return sChatRelationshipResponseVOS;
    }


    /**
     * 获取互相关注的好友ID集合
     *
     * @param userId    当前用户ID
     * @param friendIds 好友ID列表
     * @return 互相关注的好友ID集合
     */
    private Set<Long> getMutualFriendIds(Long userId, List<Long> friendIds) {
        Set<Long> mutualFriendIds = new HashSet<>();

        // 批量查询好友关系中是否有互相关注
        int batchSize = 50; // 每批处理50个
        int total = friendIds.size();

        for (int i = 0; i < total; i += batchSize) {
            int end = Math.min(i + batchSize, total);
            List<Long> batchIds = friendIds.subList(i, end);

            // 查询当前批次的好友是否关注了当前用户
            List<SChatRelationship> mutualRelations = sChatRelationshipService.queryAllByCondition(new SChatRelationship() {{
                setFriendId(userId);
                setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
            }});

            // 提取当前批次中互相关注的用户ID
            mutualRelations.stream()
                    .map(SChatRelationship::getUserId)
                    .filter(batchIds::contains)
                    .forEach(mutualFriendIds::add);
        }

        return mutualFriendIds;
    }


    @Override
    public Boolean isBlocked(Long userId, Long receiverId) {
        SChatRelationship queryEntity = new SChatRelationship();
        queryEntity.setUserId(userId);
        queryEntity.setFriendId(receiverId);
        queryEntity.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        SChatRelationship sChatRelationship = sChatRelationshipService.queryByCondition(queryEntity);
        return sChatRelationship != null && !Objects.equals(sChatRelationship.getIsBlocked(), IS_BLOCKED_NO);
    }

    @Override
    public SChatRelationshipResponseVO getFollowAndFansCount(Long userId) {
        SChatRelationshipResponseVO responseVO = new SChatRelationshipResponseVO();
        responseVO.setFansCount(sChatRelationshipService.count(new SChatRelationship() {{
            setFriendId(userId);
            setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        }}).intValue());
        responseVO.setFollowCount(sChatRelationshipService.count(new SChatRelationship() {{
            setUserId(userId);
            setIsBlocked(IS_BLOCKED_NO);
            setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        }}).intValue());
        responseVO.setBlockCount(sChatRelationshipService.count(new SChatRelationship() {{
            setUserId(userId);
            setIsBlocked(IS_BLOCKED_YES);
            setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getVal());
        }}).intValue());
        return responseVO;
    }
}
